package ml.exp;

import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

//一个基本的画四边形的GL封装
public class glquad {
    //使用GLES20 实现，保持最大兼容性
    private float[] triangleCoords = new float[]
            {
                    -1f, -1f, 0.0f, 0, 0,      // 1
                    1f, -1f, 0.0f, 1, 0, //2
                    -1f, 1f, 0.0f, 0, 1,//3
                    -1f, 1f, 0.0f, 0, 1,//3
                    1f, -1f, 0.0f, 1, 0,//2
                    1f, 1f, 0.0f, 1, 1,//4
            };
    private float[] uvCoords = new float[]
            {
                    0, 0,      // 1
                    1, 0, //2
                    0, 1,//3
                    0, 1,//3
                    1, 0,//2
                    1, 1,//4
            };
    private ByteBuffer vertexBuffer;
    private ByteBuffer uvBuffer;

    private String shaderCodeVS =
            "attribute vec4 vPosition;\n" +
                    "attribute vec2 vUv;\n" +
                    "varying vec2 v_texcoord;\n" +
                    "void main() {\n" +
                    "  v_texcoord =vUv;\n" +
                    "  gl_Position = vPosition;\n" +
                    "}\n";
    private String shaderCodeFS =
            "#extension GL_OES_EGL_image_external : require\n" +
                    "precision mediump float;\n" +
                    "varying vec2 v_texcoord;\n" +
                    "uniform sampler2D u_texture;\n" +
                    "void main() {\n" +
                    " gl_FragColor = texture2D(u_texture, v_texcoord);\n" +
//                    " gl_FragColor.r += 0.5;" +
                    " gl_FragColor.a =1.0;" +
                    "}\n";
    private static final String shaderCodeFS_OES =
            "#extension GL_OES_EGL_image_external : require\n" +
                    "precision mediump float;\n" +      // highp here doesn't seem to matter
                    "varying vec2 v_texcoord;\n" +
                    "uniform samplerExternalOES u_texture;\n" +
                    "void main() {\n" +
                    "    gl_FragColor = texture2D(u_texture, v_texcoord);\n" +
                    "}\n";
    public int texid;
    public int texid_rt;

    public int texid_new=0;
    public int fboid;
    private int shaderProg;
    private int shaderProgOES;

    public void Init() {
        //GLES20.glDisable(GLES20.GL_CULL_FACE);
        //填充订单数据
        vertexBuffer = ByteBuffer.allocateDirect(triangleCoords.length * 4);
        uvBuffer = ByteBuffer.allocateDirect(uvCoords.length * 4);
        FloatBuffer fb = vertexBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
        fb.put(triangleCoords);
        vertexBuffer.position(0);
        FloatBuffer fb2 = uvBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
        fb2.put(uvCoords);
        uvBuffer.position(0);

        Log.w("==E==", "Init GLES20 buf.");

        int shaderVS = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        // 把着色器和代码关联,然后编译着色器
        GLES20.glShaderSource(shaderVS, shaderCodeVS);
        GLES20.glCompileShader(shaderVS);
        int shaderFS = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(shaderFS, shaderCodeFS);
        GLES20.glCompileShader(shaderFS);
        String info = GLES20.glGetShaderInfoLog(shaderFS);
        Log.w("==E==", "Shader result=" + info);
        int shaderFSOES = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(shaderFSOES, shaderCodeFS_OES);
        GLES20.glCompileShader(shaderFSOES);

        this.shaderProg = GLES20.glCreateProgram();
        GLES20.glAttachShader(shaderProg, shaderVS);
        GLES20.glAttachShader(shaderProg, shaderFS);
        GLES20.glLinkProgram(shaderProg);

        this.shaderProgOES = GLES20.glCreateProgram();
        GLES20.glAttachShader(shaderProgOES, shaderVS);
        GLES20.glAttachShader(shaderProgOES, shaderFSOES);
        GLES20.glLinkProgram(shaderProgOES);

        int element = 5;
        int stride = 20;

        Log.w("==E==", "Init GLES20 quad.");
        int position = GLES20.glGetAttribLocation(shaderProg, "vPosition");
        GLES20.glEnableVertexAttribArray(position);

        int uv = GLES20.glGetAttribLocation(shaderProg, "vUv");
        GLES20.glEnableVertexAttribArray(uv);

        GLES20.glVertexAttribPointer(
                position, 3, GLES20.GL_FLOAT,
                false, 20, vertexBuffer);
        GLES20.glVertexAttribPointer(
                uv, 2, GLES20.GL_FLOAT,
                false, 8, uvBuffer);
        GLES20.glUseProgram(shaderProg);


        //InitTexOES();
        //InitTex_RT(width, height);
    }

    void InitTexOES() {
        int[] texs = new int[1];

        GLES20.glGenTextures(1, texs, 0);
        this.texid = texs[0];
        //GLES20.glTexImage2D();

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        //GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        int textureLoc = GLES20.glGetUniformLocation(shaderProg, "u_texture");

        int textureLoc2 = GLES20.glGetUniformLocation(shaderProgOES, "u_texture");
        GLES20.glUniform1i(textureLoc, 0);


    }

    int width_rt;
    int height_rt;
    ByteBuffer pixel;

    public void InitTex_RT(int width, int height) {
        int[] texs = new int[1];
        int[] bufs = new int[1];
        GLES20.glGenTextures(1, texs, 0);
        this.texid_rt = texs[0];

        GLES20.glGenTextures(1, texs, 0);
        this.texid_new = texs[0];

        GLES20.glGenFramebuffers(1, bufs, 0);
        this.fboid = bufs[0];

        //可以缩放
        width_rt = width / 2;
        height_rt = height / 2;

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texid_rt);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width_rt, height_rt, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboid);
        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texid_rt, 0);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

        pixel = ByteBuffer.allocateDirect(width_rt * height_rt * 4);
        pixel.order(ByteOrder.nativeOrder());


        //创建一个无用的Tex

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid_new);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width_rt, height_rt, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

    }


    public void Draw2Screen_OES() {
        //GLES20.glClearColor(0.5f, 0.5f, 0, 0);
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);

        GLES20.glUseProgram(shaderProgOES);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();
    }

    public void Draw2Screen_RT() {
        //GLES20.glClearColor(0.5f, 0, 0.5f, 0);
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);

        GLES20.glUseProgram(shaderProg);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid_rt);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();

    }
    public  void SetPixel(ByteBuffer buffer,int width_rt,int height_rt)
    {
        if(texid_new==0)
        {

            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid_new);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width_rt, height_rt, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        }
        this.width_rt =width_rt;
        this.height_rt =height_rt;
        this.pixel=buffer;
    }

    public void Draw2Screen_New() {

        {//WritePixel
            //Log.w("==E==", "draw rt time=" + (time1 - time0) + " readpixel time=" + (time2 - time1));
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid_new);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width_rt, height_rt, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixel);
            //long time3 = System.currentTimeMillis();
            //Log.w("==E==", "set img time=" + (time3 - time2));
        }
        //GLES20.glClearColor(0.5f, 0, 0.5f, 0);
        //GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        //GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);

        GLES20.glUseProgram(shaderProg);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid_new);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();

    }
    public  void  Draw2Screen_Custom(int texid)
    {
        GLES20.glUseProgram(shaderProg);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();
    }

    public void Draw2RT_OES() {

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboid);

        GLES20.glViewport(0, 0, width_rt, height_rt);
        GLES20.glClearColor(0f, 0f, 1.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);


        GLES20.glUseProgram(shaderProgOES);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    }
    public  void  Draw2Pixel_OES()
    {
        //long time0 = System.currentTimeMillis();
        {//Draw 2 RT
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboid);

            GLES20.glViewport(0, 0, width_rt, height_rt);
            GLES20.glClearColor(0f, 0f, 1.0f, 1.0f);
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);


            GLES20.glUseProgram(shaderProgOES);
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid);
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
            GLES20.glFlush();

        }

        //long time1 = System.currentTimeMillis();
        {//read pixel
            pixel.position(0);
            GLES20.glReadPixels(0, 0, width_rt, height_rt,
                    GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixel);
        }
        //long time2 = System.currentTimeMillis();

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

    }


}
